package anet

import "gitee.com/AlexWoo/arpc/trace"

// Msg Header
var (
	anetMsgTypeKey      = trace.Key("anet.msg.type")
	anetMsgCodeKey      = trace.Key("anet.msg.code")
	anetMsgAppIdKey     = trace.Key("anet.msg.appid")
	anetMsgChannelIdKey = trace.Key("anet.msg.channel_id")
	anetMsgUserIdKey    = trace.Key("anet.msg.user_id")
	anetMsgSerialIdKey  = trace.Key("anet.msg.serial_id")
	anetMsgDstKey       = trace.Key("anet.msg.dst")
	anetMsgSubtypeKey   = trace.Key("anet.msg.subtype")
)

// Msg Type
var (
	anetMsgTypeJoin    = anetMsgTypeKey.String("Join")
	anetMsgTypeLeave   = anetMsgTypeKey.String("Leave")
	anetMsgTypeMessage = anetMsgTypeKey.String("Message")
	anetMsgTypeNotify  = anetMsgTypeKey.String("Notify")
	anetMsgTypeClosed  = anetMsgTypeKey.String("Closed")
	anetMsgTypeUpdate  = anetMsgTypeKey.String("Update")
)

// Msg Code
var (
	anetMsgRequest                 = anetMsgCodeKey.String("Request")
	anetMsgCodeOK                  = anetMsgCodeKey.String("OK")
	anetMsgCodeUnexpectedAppID     = anetMsgCodeKey.String("UnexpectedAppID")
	anetMsgCodeUnexpectedChannelID = anetMsgCodeKey.String("UnexpectedChannelID")
	anetMsgCodeUnexpectedUserID    = anetMsgCodeKey.String("UnexpectedUserID")
	anetMsgCodeBadRequest          = anetMsgCodeKey.String("BadRequest")
	anetMsgCodeIllegalRequest      = anetMsgCodeKey.String("IllegalRequest")
	anetMsgCodeSessionNotExist     = anetMsgCodeKey.String("SessionNotExist")
	anetMsgCodeRequestDiscard      = anetMsgCodeKey.String("RequestDiscard")
	anetMsgCodeRequestTimeout      = anetMsgCodeKey.String("RequestTimeout")
)

func anetAttributeFromanetMsg(msg *Msg, s *session) []trace.KeyValue {
	attrs := []trace.KeyValue{}

	switch msg.Type {
	case MsgType_Join:
		attrs = append(attrs, anetMsgTypeJoin)
	case MsgType_Leave:
		attrs = append(attrs, anetMsgTypeLeave)
	case MsgType_Message:
		attrs = append(attrs, anetMsgTypeMessage)
	case MsgType_Notify:
		attrs = append(attrs, anetMsgTypeNotify)
	case MsgType_Closed:
		attrs = append(attrs, anetMsgTypeClosed)
	case MsgType_Update:
		attrs = append(attrs, anetMsgTypeUpdate)
	}

	switch msg.Code {
	case 0:
		attrs = append(attrs, anetMsgRequest)
	case OK:
		attrs = append(attrs, anetMsgCodeOK)
	case UnexpectedAppID:
		attrs = append(attrs, anetMsgCodeUnexpectedAppID)
	case UnexpectedChannelID:
		attrs = append(attrs, anetMsgCodeUnexpectedChannelID)
	case UnexpectedUserID:
		attrs = append(attrs, anetMsgCodeUnexpectedUserID)
	case BadRequest:
		attrs = append(attrs, anetMsgCodeBadRequest)
	case IllegalRequest:
		attrs = append(attrs, anetMsgCodeIllegalRequest)
	case SessionNotExist:
		attrs = append(attrs, anetMsgCodeSessionNotExist)
	case RequestDiscard:
		attrs = append(attrs, anetMsgCodeRequestDiscard)
	case RequestTimeout:
		attrs = append(attrs, anetMsgCodeRequestTimeout)
	default:
		attrs = append(attrs, anetMsgCodeKey.Int(int(msg.Code)))
	}

	attrs = append(attrs, anetMsgAppIdKey.String(msg.AppId))
	attrs = append(attrs, anetMsgChannelIdKey.String(msg.ChannelId))
	attrs = append(attrs, anetMsgUserIdKey.String(msg.UserId))
	attrs = append(attrs, anetMsgSerialIdKey.Int64(int64(msg.SerialId)))

	if msg.Dst != "" {
		attrs = append(attrs, anetMsgDstKey.String(msg.Dst))
	}

	if msg.SubType != 0 {
		attrs = append(attrs, anetMsgSubtypeKey.Int(int(msg.SubType)))
	}

	attrs = append(attrs, anetAttributeFromSessionState(s)...)

	return attrs
}

// Session Header
var (
	anetSessionAppId     = trace.Key("anet.session.app_id")
	anetSessionChannelId = trace.Key("anet.session.channel_id")
	anetSessionUserId    = trace.Key("anet.session.user_id")
	anetSessionConnIdKey = trace.Key("anet.session.conn_id")
	anetSessionRemoteKey = trace.Key("anet.session.remote")
	anetSessionLocalKey  = trace.Key("anet.session.local")
)

func anetAttributeFromSession(s *session) []trace.KeyValue {
	attrs := []trace.KeyValue{
		anetSessionAppId.String(s.appid),
		anetSessionChannelId.String(s.channelid),
		anetSessionUserId.String(s.userid),
	}

	// TODO ConnectionID, Local Address and Remote Address

	return attrs
}

// Session state Header
var (
	anetSessionStateKey         = trace.Key("anet.session.state")
	anetSessionUpdateTimeoutKey = trace.Key("anet.session.update_timeout")
	anetSessionSendbufSizeKey   = trace.Key("anet.session.sendbuf_size")
)

// Session state
var (
	anetSessionStateSessionNormal  = anetSessionStateKey.String("session_normal")
	anetSessionStateConnClosed     = anetSessionStateKey.String("conn_closed")
	anetSessionStateSessionClosing = anetSessionStateKey.String("session_closing")
	anetSessionStateSessionClosed  = anetSessionStateKey.String("session_closed")
	anetSessionStateUnknown        = anetSessionStateKey.String("session_unknown")
)

func anetAttributeFromSessionState(s *session) []trace.KeyValue {
	attrs := []trace.KeyValue{}

	// Session State
	switch s.state {
	case sessionNormal:
		attrs = append(attrs, anetSessionStateSessionNormal)
	case connClosed:
		attrs = append(attrs, anetSessionStateConnClosed)
	case sessionClosing:
		attrs = append(attrs, anetSessionStateSessionClosing)
	case sessionClosed:
		attrs = append(attrs, anetSessionStateConnClosed)
	default:
		attrs = append(attrs, anetSessionStateUnknown)
	}

	// Session Timeout and SendbufSize
	attrs = append(attrs, anetSessionUpdateTimeoutKey.Int(int(s.updateTimeout)))
	attrs = append(attrs, anetSessionSendbufSizeKey.Int(int(s.sendbuf.BufferSize())))

	return attrs
}
